package recherche;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;

import parser.ParserTermeHandler;

import modex.Document;
import modex.Paragraphe;
import modex.Terme;
import modex.TermePara;
import bddaccess.DAO;
import bddaccess.DAOFactory;
import bddaccess.DocumentDAO;
import bddaccess.ParagrapheDAO;
import bddaccess.TermeDAO;
import bddaccess.TermeParaDAO;

public class ModuleRecherche {

	// ArrayList permettant de stocker la stop list
	private ArrayList<String> stopList;

	public ModuleRecherche(){
		this.stopList = new ArrayList<String>();
		this.initStopList();
	}
	
	public ArrayList<Paragraphe> executeQuery(String queryElements){
		// Liste des paragraphes pertinents
		ArrayList<Paragraphe> outputP = new ArrayList<Paragraphe>();
		// Permet de stocker les mots clés de la recherche
		ArrayList<String> arrayQueryElements = new ArrayList<String>();
		
		/* RECUPERATION DES MOTS CLES DE LA REQUETE */
		
		// Récupération des mots clés grâce à la regExp
    	String[] keyWords = queryElements.toString().split(ParserTermeHandler.REGEXP, -1);
		
    	// Elimination des mots contenus dans la stopList
		for (String keyWord : keyWords){
			
			// On rejette les termes "vides"
			if (!keyWord.equals("")) {
				// On rejette les termes de la stopList
				if (!this.stopList.contains(keyWord.trim().toLowerCase())) {
					arrayQueryElements.add(keyWord.trim().toLowerCase());
				}
			}
		}

		// Liste des Terme associés aux mots clés de la requête
		ArrayList<Terme> termesRequete = new ArrayList<Terme>();
		Terme termeCourant = new Terme();
		TermeDAO termeDao = DAOFactory.getTermeDAO();
		
		// Liste des TermePara
		ArrayList<TermePara> termesParas = new ArrayList<TermePara>();
		// Liste de test TODO à enlever !!
		ArrayList<TermePara> tp2 = new ArrayList<TermePara>();
		//TermePara termePara = new TermePara();
		TermeParaDAO termeParaDao = DAOFactory.getTermeParaDAO();
		
		System.out.println("*** Mots de la requête ***");
		for (String s : arrayQueryElements){
			System.out.print(s+" -> ");
			
			String terme;
			// Lemmatisation du terme
			if (s.trim().length() > 7) {
				terme = s.trim().toLowerCase().substring(0, 7);
			} else {
				terme = s.trim().toLowerCase();
			}
			
			termeCourant = termeDao.find(terme);
			if (termeCourant != null) { 
				/* Le mot est connu dans la bdd */
				System.out.println("Recherche de "+
						termeCourant.getValueTerme()+
						" dans les paragraphes"); 
				
				/* On récupère l'objet Terme associé */
				termesRequete.add(termeCourant);
				
				/* On cherche les associations TermePara contenant ce Terme 
				 * c'est-à-dire on cherche les paragraphes contenant ce mot
				 * Rmq: on sait que le retour ne sera pas vide car on a déjà rencontré ce mot
				 * */				
				tp2 = termeParaDao.findParas(termeCourant.getIdTerme());
				System.out.println(tp2.size()+
					" paragraphe(s)contenant ce mot.");
				
//				for(TermePara termePara : tp2) {			
//					System.out.println("{ " + termePara.getIdTerme() + ", " + termePara.getIdPara() + " }");
//				}
				
				ArrayList<TermePara> aInserer = new ArrayList<TermePara>();
				for(TermePara termePara : tp2) {					
					if(!this.paraDejaRencontre(termesParas, termePara)) {						
						aInserer.add(termePara);
					}
				}
				
				termesParas.addAll(aInserer);	
			}
			else { 
				/* Le mot n'existe pas dans la bdd */
				System.out.println("Le mot n'est pas connu."); 
			}			
		}
		
		System.out.println(termesParas.size()+
			" paragraphe(s)retournés par la requête.");
		
//		for(TermePara termePara : termesParas) {			
//			System.out.println("{ " + termePara.getIdTerme() + ", " + termePara.getIdPara() + " }");
//		}
		
		// Trier les paragraphes du meilleur au plus faible score
		//this.trierParagraphes(termesParas);
		Collections.sort(termesParas, Collections.reverseOrder());
		System.out.println("meilleur { " + 
				termesParas.get(0).getIdPara() + 
				", score = " + termesParas.get(0).getScore() + 
				" }");
		System.out.println("pire { " + 
				termesParas.get(termesParas.size()-1).getIdPara() + 
				", score = " + termesParas.get(termesParas.size()-1).getScore() + 
				" }");
		
		// TODO Corriger les pbs d'encodage (gouière -> goutiã¨re)
		
		ParagrapheDAO paraDao = DAOFactory.getParagrapheDAO();
		Paragraphe para = null;

		for (TermePara tp : termesParas){
			para = paraDao.find(tp.getIdPara());
			if (para != null){
				outputP.add(para);
			}
		}
		
		this.writeOutputFile(outputP);
		
		return outputP;		
	}
	
	private boolean paraDejaRencontre(ArrayList<TermePara> termesParas, TermePara tp) {
		boolean dejaRencontre = false;
		
		for(TermePara termePara : termesParas) {			
			if(termePara.getIdPara() == tp.getIdPara()) { 
				dejaRencontre = true; 
				//System.out.println("score avant = " + termePara.getScore());
				/* Mise à jour du score */
				termePara.setScore(termePara.getScore() + tp.getScore());
				//System.out.println("score après = " + termePara.getScore());
			}
		}
		
		return dejaRencontre;
	}
	
	private void initStopList(){
    	
    	BufferedReader br = null;
		try {
			// Récupération du fichier
			InputStream is = new FileInputStream("resources/StopList.txt");
			 
			// Récupération d'un BufferedReader pour lire le fichier
			InputStreamReader isr = new InputStreamReader(is);
			br = new BufferedReader(isr);
			String line = "";
			
			// Parcours du fichier ligne par ligne et ajout des termes à l'ArrayList
		    while ((line = br.readLine()) != null) {
		        this.stopList.add(line);
		    }
		
		} catch (IOException e) {
			System.err.println(e.toString());
		} finally {
		     try {
		         if (br != null) {
		             br.close();
		         }
		     } catch (IOException e) {
		    	 System.err.println(e.toString());
		     }
		}
    }
	
	public void writeOutputFile(ArrayList<Paragraphe> paras){
		String fichier = "resources/qrel.txt"; 
		DocumentDAO docDAO = DAOFactory.getDocumentDAO();
		Document doc = null;
		
		try {
			FileWriter fw = new FileWriter (fichier);
			BufferedWriter bw = new BufferedWriter (fw);
			PrintWriter fichierSortie = new PrintWriter (bw); 
			
			for (Paragraphe p : paras){
				doc = docDAO.find(p.getIdDocument());
				if (doc !=null){
					fichierSortie.println(doc.getNomDocument()+".xml\t"+p.getxPath());
				}
			}
			fichierSortie.close(); 
		}
		catch (Exception e){
			System.err.println(e.toString());
		}		
	}
}
